import Events from 'events'; // 事件监听器
import { fabric } from 'fabric';
import type { IBasePaletteOption } from './types/BasePalette.type';
import { ECursorType, type EventMap } from './types/BasePalette.type';

export class BasePalette {
  //  *** 画布相关 ***
  protected wrapper!: HTMLDivElement | null; // 画布容器
  protected canvasEl!: HTMLCanvasElement;
  protected canvas!: fabric.Canvas;

  // *** 场景相关 ***
  protected sceneWidth = 0;
  protected sceneHeight = 0;
  protected resizeObserverIns: ResizeObserver | null = null;
  protected zoom = 1;
  protected maxZoomFactor = 10; // 最大缩放倍数
  protected minZoomFactor = 0.5; // 最小缩放倍数

  // *** 事件处理相关 ***
  protected eventListener: Events<EventMap> = new Events<EventMap>();

  constructor(option: IBasePaletteOption) {
    const { wrapper } = option;
    if (!wrapper) {
      throw new Error(
        'sorry you must provide an HTMLDivElement as this wrapper container',
      );
    }
    this.wrapper = wrapper;
    this.sceneWidth = wrapper.scrollWidth || 0;
    this.sceneHeight = wrapper.scrollHeight || 0;
    this.init();
  }

  /**
   *  ***************************************************************
   *  ************************  初始化相关  *************************
   *  ***************************************************************
   */

  /**
   * @description 初始化
   * @param {}
   * @returns {}
   */
  protected init() {
    this.createCanvasElement();
    this.initCanvas();
  }

  /**
   * @description 创建canvas 元素
   * @param {}
   * @returns {}
   */
  protected createCanvasElement() {
    if (!this.wrapper) return;
    this.wrapper.style.position = 'relative';
    this.canvasEl = document.createElement('canvas');
    this.canvasEl.style.cssText = `
      width: 100%;
      height: 100%;
    `;
    this.wrapper.childNodes.forEach((child) => {
      this.wrapper && this.wrapper.removeChild(child);
    });
    this.wrapper.appendChild(this.canvasEl);
  }

  /**
   * @description 初始化画布
   * @param {}
   * @returns {}
   */
  protected initCanvas() {
    const option = {
      width: this.sceneWidth,
      height: this.sceneHeight,
      selection: false,
      enableRetinaScaling: true,
    };

    this.canvas = new fabric.Canvas(this.canvasEl, option);
    this.setCursor(ECursorType.DEFAULT);
  }

  /**
   * @description 设置鼠标光标
   * @param {eMarkToolType | null} tool
   * @returns {void}
   */
  setCursor(type: ECursorType | string) {
    this.canvas.setCursor(type);
    this.canvas.moveCursor = type;
    this.canvas.hoverCursor = type;
    this.canvas.defaultCursor = type;
  }

  /**
   * @description 事件触发器
   * @param {}
   * @returns {}
   */
  protected emit = this.eventListener.emit.bind(this.eventListener);

  /**
   * @description 注册事件监听
   * @param {}
   * @returns {}
   */
  on = this.eventListener.on.bind(this.eventListener);

  /**
   * @description 注册事件监听(只执行一次)
   * @param {}
   * @returns {}
   */
  once = this.eventListener.once.bind(this.eventListener);

  /**
   * @description 销毁事件监听
   * @param {}
   * @returns {}
   */
  off = this.eventListener.off.bind(this.eventListener);
}
